import {Rehydrater} from "./Rehydraters"
export function assert_log()
{

    return function(tarage:any, methodName: string, desc:any){


        var methodFun = desc.value;
        desc.value = function(...args:any)
        {
            const cpubegin = Game.cpu.getUsed();

           const ret =  methodFun.apply(this,args); // 执行输出 我是getData方法\
           const name  = `${tarage.constructor.name}:${methodName}`;
            const cpuend = Game.cpu.getUsed();

            return ret;
        }
     }
}

export function cpu_used(getkey?:(...args:any)=>string ,isoutput:(...args:any)=>boolean= (...args:any)=>{return true},output:(...args:any)=>void= (...args:any)=>
{
    console.log(args[0]);
})
{

    return function(tarage:any, methodName: string, desc:any){


        var methodFun = desc.value;
        desc.value = function(...args:any)
        {
            const cpubegin = Game.cpu.getUsed();

           const ret =  methodFun.apply(this,args); // 执行输出 我是getData方法\
            const cpuend = Game.cpu.getUsed();
            if(isoutput(...args,cpuend -cpubegin))
            {
                output(`[${getkey?getkey(...args):""}]${tarage.constructor.name}:${methodName} [${cpuend -cpubegin }]`,...args)
                // console.log(`[${getkey?getkey(...args):""}]${tarage.constructor.name}:${methodName} [${cpuend -cpubegin }]`);
            }
           


            return ret;
        }
     }
}
export interface getKey
{
    (obj:any):string
}
 
 
export function memory_cache(cache_address:string[]):any
{
    // Memory.Debug[`cache games`] = Game.time;
    if(!Memory.Data)
    {
        Memory.Data={};
    }
    let preRoot = Memory.Data;
    while(cache_address.length>=1)
    {
        const key = cache_address[0];
        cache_address.splice(0,1);
        if(preRoot[key])
        {
            preRoot = preRoot[key]
        }
        else
        {
            preRoot[key] ={};
            preRoot =  preRoot[key];
        }
    }
    return function(target:any, propertyname: string)
    {
        if(!preRoot[propertyname])
        {
            preRoot[propertyname]={};
        }
        Object.defineProperty(target, propertyname, {
            get(): unknown {
              return  (preRoot[propertyname]);
            },
            set(newValue: unknown) {
              return preRoot[propertyname]= newValue;
            },
            enumerable: true
          });
    }
}
export function CacheReturn(Objectkey:string)
{

    return function(tarage:any, methodName: string, desc:any){


        var methodFun = desc.value;
        desc.value = function(...args:any)
        { // 重写 getData 方法
            if(this[Objectkey])
            {
                return this[Objectkey]
            }
            const ret =  methodFun.apply(this,args);
            this[Objectkey]= ret;
            return ret;
        }
     }
}

function key(arg0: any): any {
    throw new Error("Function not implemented.");
}


export function keyByGuid(target:any)
{
    return target.GUID;
}
 

export function memory_cache_by(cache_address:string[],key:getKey):any
{

    // Memory.Debug[`cache games`] = Game.time;
    if(!Memory.Data)
    {
        Memory.Data={};
    }
    let preRoot = Memory.Data;
    while(cache_address.length>=1)
    {
        const key = cache_address[0];
        cache_address.splice(0,1);
        if(preRoot[key])
        {
            preRoot = preRoot[key]
        }
        else
        {

            // if(global.GameLoop.GameEngine.EntityManager.Entities[])
            preRoot[key] ={};
            preRoot =  preRoot[key];
        }
    }
    return function(target:any, propertyname: string)
    {
        console.log(`target  propertyname:${propertyname}`);
        Object.defineProperty(target, propertyname, {
            get(): unknown {
                let guid = key(this);
                if(!guid)
                {
                    return
                }

                if(!preRoot[guid])
                {
                    preRoot[guid]={};

                }
                return (preRoot[guid][propertyname])

            },
            set(newValue: unknown) {
                let guid = key(this);
                if(!guid)
                {
                    return
                }

                if(!preRoot[guid]  )
                {
                    preRoot[guid]={};
                }
                return preRoot[guid][propertyname]= newValue;

            },
            enumerable: true
          });
    }
}
  



export function heapcache_roomposition():any
{
    return function(tarage:RoomPosition, methodName: string, desc:any){
        var methodFun = desc.value;
        desc.value = function(...args:any)
        { // 重写 getData 方法
            const a = Game.cpu.getUsed();
            const key = `${tarage.roomName}_${tarage.x}_${tarage.y}`;
            let cachemap = global.heapcache.pos[key];
            if(cachemap)
            {
                const b = Game.cpu.getUsed();
                if(b-a>0.5)
                {
                    console.log(`get roomposition cpu`,`${b-a}`);
                }
                return cachemap
            }
      
            const ret =  methodFun.apply(this,args);
            const key2 = `${ret.roomName}_${ret.x}_${ret.y}`;
  
            global.heapcache.pos[key2]=ret;
            const b = Game.cpu.getUsed();
            if(b-a>0.5)
            {
                console.log(`create roomposition cpu`,`${b-a}`);
            }
            
            return ret;
        }
     }
}

// 使用函数的第一个参数缓存
export function cache_key_arg0(store_key:string,funcName:string,param:string[])
{
    return `${store_key}${funcName}${param[0]}`
}
export function cache_key_module_pos(store_key:string,funcName:string ,arg:any[],moduleType?:string)
{
    let val = arg[0].x+arg[0].y*50;
    if(arg[1])
    {
        val+=arg[1].x+arg[1].y*50;
    }
    return `${store_key}${funcName}${moduleType}${val}`
}

/**
 *
 * @param store_key 存储的键值前缀 key为 store_key+ methodName || store_key+ keygetter()
 * @param interval 缓存的事件间隔 0缓存1tick -1 永久缓存
 * @param keygetter
 * @returns
 */
export function cache_return(store_key:string,interval:number,keygetter?:cache_key_arg0 ):any
{
    return function(tarage:any, methodName: string, desc:any){
        // target 应该是原型对象

        var methodFun = desc.value;
        desc.value = function(...args:any)
        {


            const store_id =keygetter?keygetter(store_key,methodName,args,this.type): store_key+methodName;
            // global.Log.Info(`缓存的key ${store_id}`);
            if(!this[store_id] || ( interval>=0 && this[store_id].expire<Game.time))
            {
                // 过期了 或者不存在
                // this 才是真实的对象
                const ret =  methodFun.apply(this,args);
                if(ret)
                {
                    
                }
                this[store_id]={
                    expire:Game.time+interval,
                    ret:ret
                }
            }
            return this[store_id].ret;
        }
     }
}

/**
 *
 * @param store_key 存储的键值前缀 key为 store_key+ methodName || store_key+ keygetter()
 * @param interval 缓存的事件间隔 0缓存1tick -1 永久缓存
 * @param keygetter
 * @returns
 */
export function cache_return_Constant( keygetter:(...arg:any)=>string=( methodName,...args)=>methodName):any
{
    return function(tarage:any, methodName: string, desc:any){
        // target 应该是原型对象
        var methodFun = desc.value;
        desc.value = function(...args:any)
        {
            const store_id =keygetter(methodName,...args)
            // global.Log.Info(`缓存的key ${store_id}`);
            if(!this[store_id])
            {
                // 过期了 或者不存在
                const ret =  methodFun.apply(this,args);
                this[store_id]=ret
            }
            return this[store_id] ;
        }
     }
}
/**
 *
 * @param store_key 存储的键值前缀 key为 store_key+ methodName || store_key+ keygetter()
 * @param interval 缓存的事件间隔 0缓存1tick -1 永久缓存
 * @param keygetter 属性拼接唯一值
 * @returns 间隔执行函数
 */
export function interval_execute(store_key:string,interval_arg:number|string,keygetter?:cache_key_arg0):any
{
    return function(tarage:any, methodName: string, desc:any){
        // target 应该是原型对象
     
        var methodFun = desc.value;
        desc.value = function(...args:any)
        {
            let interval = typeof interval_arg =="number"?interval_arg:this[interval_arg]
           
            const store_id =keygetter?keygetter(store_key,methodName,args,this.type): store_key+methodName;
            if(this[interval_arg])
            {
                Memory.Debug[`缓存间隔${store_id}`] = this[interval_arg];
            }
            // global.Log.Info(`缓存的key ${store_id}`);
            if(!this[store_id] || ( interval>=0 && this[store_id].expire<Game.time))
            {
                // 过期了 或者不存在
                // this 才是真实的对象
                methodFun.apply(this,args);

                this[store_id]={
                    expire:Game.time+interval,
                }
            }
            return this[store_id].ret;
        }
     }
}

